use actix_web::{HttpResponse, HttpRequest};
use fluffy::{
    response, request, db, model::{Db, Model}, utils, datetime,
    constants::AUTHORIZATION,
};
use crate::models::{Users as UserIndex, UserCodes, Links, LinksPager};
use redis::Commands;

type UserInfo = (usize, String, usize, String, usize, usize);
type UserCode = (usize, usize, String, String, usize);
type UserLink = (usize, String, String, String, usize);

/// 检测token是否正常
fn has_login(req: &HttpRequest) -> bool { 
    let auth_string = if let Some(v) = req.headers().get(AUTHORIZATION) { v.to_str().unwrap() } else { return false; };
    let auth_arr = auth_string.split(" ").collect::<Vec<&str>>();
    if auth_arr.len() == 1 { 
        return false;
    }
    let encrypt = utils::md5_str(auth_arr[1]);
    let key = format!("token-{}", encrypt);
    let mut cache = fluffy::cache::get_conn();
    if let Ok(v) = cache.get::<&str, String>(&key) { 
        if v != "" && v.contains("|") { return true; };
    }
    false
}

/// 会员中心默认主页
pub  async fn index(req: HttpRequest) -> HttpResponse {
    if !has_login(&req) { 
        return response::error("还未登录或者Token已失效");
    }
    let token = request::get_token(&req);
    let sql_find = &format!("SELECT id, name, last_login, last_ip, login_count, created FROM users WHERE id = '{}'", token.id);
    let mut conn = db::get_conn();
    let result = if let Some(v) = Db::query_first(&mut conn, sql_find) {
        let (id, name, last_login, last_ip, login_count, created): UserInfo = from_row!(v);
        UserIndex { 
            id, name, last_ip, login_count, 
            last_login: datetime::datetime(last_login as i64), 
            created: datetime::datetime(created as i64)
        }
    } else { UserIndex::default() };
    response::result(&result)
}

/// 开发信息
pub async fn dev(req: HttpRequest) -> HttpResponse {
    if !has_login(&req) { 
        return response::error("还未登录或者Token已失效");
    }
    let token = request::get_token(&req);
    let query = query![
        fields => &"id, user_id, user_name, code, created",
    ];
    let cond = cond![
        "user_id" => &token.id,
    ];
    let mut conn = db::get_conn();
    let result = if let Some(v) = UserCodes::fetch_row(&mut conn, &query, Some(&cond)) {
        let (id, user_id, user_name, code, created): UserCode = from_row!(v);
        UserCodes { id, user_id, user_name, code, created: datetime::datetime(created as i64) }
    } else { UserCodes::default() };
    response::result(&result)
}

/// 链接
pub async fn links(req: HttpRequest) -> HttpResponse {
    if !has_login(&req) { 
        return response::error("还未登录或者Token已失效");
    }
    let token = request::get_token(&req);
    let mut query = query![ fields => "id, origin_url, code, image, created", ];
    query.set_limit_offset(&req);
    let cond = cond![ "user_id" => &token.id, ];
    let mut conn = db::get_conn();
    let rows = Links::fetch_rows(&mut conn, &query, Some(&cond));
    let mut links: Vec<Links> = vec![];
    for r in rows { 
        let (id, origin_url, code, image, created): UserLink = from_row!(r);
        links.push(Links{id, origin_url, code, image, created: datetime::datetime(created as i64)});
    }
    links.shrink_to_fit();
    let result = LinksPager { 
        rows: links,
        pager: Links::get_pager(&mut conn, &query, Some(&cond)),
    };
    response::result(&result)
}

/// 退出登录
pub async fn logout(req: HttpRequest) -> HttpResponse { 
    if !has_login(&req) { 
        return response::error("还未登录或者Token已失效");
    }
    let auth_string = if let Some(v) = req.headers().get(AUTHORIZATION) { v.to_str().unwrap() } else { 
        return response::error("无效的Token");
    };
    let encrypt = utils::md5_str(&auth_string);
    let key = format!("token-{}", encrypt);
    let mut cache = fluffy::cache::get_conn();
    cache.del::<&str, usize>(&key).unwrap();
    response::ok()
}
